﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.BlogCore.SqlSugar
 * 唯一标识：cd3b60b4-182e-4d4c-8994-5ec36d82a02a
 * 文件名：SqlSugarConfig
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2024/7/23 16:50:24
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

namespace Vampirewal.BlogCore.DataAccess;

/// <summary>
/// SqlSugar配置
/// </summary>
public abstract class SqlSugarConfig
{
    /// <summary>
    /// 数据库连接对象
    /// </summary>
    public SqlSugarScope Client { get; set; }

    /// <summary>
    /// 构造函数
    /// </summary>
    public SqlSugarConfig()
    {
    }

    /// <summary>
    /// 配置Sqlsugar连接设置
    /// </summary>
    /// <param name="DbName"></param>
    /// <param name="ConnStr"></param>
    /// <param name="dbType"></param>
    /// <returns></returns>
    public virtual ConnectionConfig GetDbConnectionConfig(string DbName, string ConnStr, DbType dbType)
    {
        return new ConnectionConfig()
        {
            ConfigId = DbName,
            ConnectionString = ConnStr,//"Data Source=./demo.db",
            DbType = dbType,
            IsAutoCloseConnection = true,
            InitKeyType = InitKeyType.Attribute,
            MoreSettings = new ConnMoreSettings()
            {
                IsWithNoLockQuery = true//看这里
            },
        };
    }

    #region AOP

    /// <summary>
    /// 数据执行过滤
    /// <para>可用于新增或修改的时候，处理CreateName或UpdateName</para>
    /// </summary>
    /// <param name="OldValue"></param>
    /// <param name="entityInfo"></param>
    public virtual void DataExecuting(object OldValue, DataFilterModel entityInfo)
    {

    }

    /// <summary>
    /// 查询后数据替换
    /// </summary>
    /// <param name="value"></param>
    /// <param name="entity"></param>
    public virtual void DataExecuted(object value, DataAfterModel entity)
    {

    }

    /// <summary>
    /// SQL报错
    /// </summary>
    /// <param name="exp"></param>
    public virtual void OnError(SqlSugarException ex)
    {
        if (ex.Parametres == null) return;
        var log = $"【{DateTime.Now}——错误SQL】\r\n{UtilMethods.GetNativeSql(ex.Sql, (SugarParameter[])ex.Parametres)}\r\n";
        var originColor = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.DarkRed;
        Console.WriteLine(log);
        Console.ForegroundColor = originColor;
    }

    

    /// <summary>
    /// SQL执行完
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="para"></param>
    public virtual void OnLogExecuted(string sql, SugarParameter[] para)
    {
        GetSqlExecuteTimeMoreOnceSecond(5, sql, para);
    }

    /// <summary>
    /// SQL执行前
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="para"></param>
    public virtual void OnLogExecuting(string sql, SugarParameter[] pars)
    {
        var log = $"【{DateTime.Now}——执行SQL】\r\n{UtilMethods.GetNativeSql(sql, pars)}\r\n";
        var originColor = Console.ForegroundColor;
        if (sql.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
            Console.ForegroundColor = ConsoleColor.Green;
        if (sql.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase) || sql.StartsWith("INSERT", StringComparison.OrdinalIgnoreCase))
            Console.ForegroundColor = ConsoleColor.Yellow;
        if (sql.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase))
            Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(log);
        Console.ForegroundColor = originColor;
    }

    #endregion

    /// <summary>
    /// 获取代码执行超过1秒的代码，放在OnLogExecuted
    /// </summary>
    /// <returns>超时sql所在信息</returns>
    protected string GetSqlExecuteTimeMoreOnceSecond(double timeout,string sql, SugarParameter[] pars)
    {
        if(timeout<0)
            timeout= 1;

        if (Client.Ado.SqlExecutionTime.TotalSeconds > timeout)
        {
            var fileName = Client.Ado.SqlStackTrace.FirstFileName; // 文件名
            var fileLine = Client.Ado.SqlStackTrace.FirstLine; // 行号
            var firstMethodName = Client.Ado.SqlStackTrace.FirstMethodName; // 方法名
            var log = $"【{DateTime.Now}——超时SQL】\r\n【所在文件名】：{fileName}\r\n【代码行数】：{fileLine}\r\n【方法名】：{firstMethodName}\r\n" + $"【SQL语句】：{UtilMethods.GetNativeSql(sql, pars)}";
            var originColor = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine(log);
            Console.ForegroundColor = originColor;
        }

        return "";
    }
}

public static class SqlSugarExtension
{
    public static void AddSqlSugar(this IServiceCollection services)
    {
        var type = App.EffectiveTypes.Where(w => w.IsSubclassOf(typeof(SqlSugarConfig))).FirstOrDefault();

        if (type == null)
        {
            throw new Exception("不存在继承自SqlSugarConfig的实现！");
        }

        var config = (SqlSugarConfig)Activator.CreateInstance(type)!;

        DbBaseOptions DbOptions = App.GetConfig<DbBaseOptions>("DbBase");

        var dbConnectConfigList = new List<ConnectionConfig>();

        foreach (var item in DbOptions.ConnectionStrings ?? new List<ConnectionString>())
        {
            string connStr = item.Value;

            if (item.DbType == DbType.Sqlite)
            {
                var strs = connStr.Split('=');

                connStr = $"{strs[0]}={AppDomain.CurrentDomain.BaseDirectory}{strs[1]}";
            }

            dbConnectConfigList.Add(config.GetDbConnectionConfig(item.Key, connStr, item.DbType));
        }

        config.Client = new SqlSugarScope(dbConnectConfigList, db =>
        {
            foreach (var item in DbOptions.ConnectionStrings)
            {
                //SQL执行完
                db.GetConnection(item.Key).Aop.OnLogExecuted = config.OnLogExecuted;
                //SQL执行前
                db.GetConnection(item.Key).Aop.OnLogExecuting = config.OnLogExecuting;
                //SQL报错
                db.GetConnection(item.Key).Aop.OnError = config.OnError;
                //数据执行过滤
                db.GetConnection(item.Key).Aop.DataExecuting = config.DataExecuting;
                //查询后数据替换
                db.GetConnection(item.Key).Aop.DataExecuted = config.DataExecuted;
            }
        });

        services.AddSingleton<ISqlSugarClient>(config.Client);
        //services.AddTransient(typeof(SqlSugarRepository<>));
        services.AddTransient(typeof(SimpleClient<>));


        foreach (var item in dbConnectConfigList)
        {
            var dbProvider = config.Client.GetConnectionScope(item.ConfigId);

            if (DbOptions.IsInitDb)
                dbProvider.DbMaintenance.CreateDatabase();

            if (DbOptions.IsInitTable)
            {
                var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false)).ToList();

                foreach (var entityType in entityTypes)
                {
                    dbProvider.CodeFirst.SetStringDefaultLength(200).InitTables(entityType);
                }
            }
        }

        
    }
}